package com.hst.capacity.domain.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Filter;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.hst.capacity.domain.common.constants.Constants;
import com.hst.capacity.domain.exception.BusinessException;
import com.hst.capacity.domain.model.entity.driver.DriverCarEntity;
import com.hst.capacity.domain.model.entity.vehicle.VehicleEntity;
import com.hst.capacity.domain.model.entity.vehicle.VehicleInsuranceEntity;
import com.hst.capacity.domain.model.entity.vehicle.VehicleLicenseEntity;
import com.hst.capacity.domain.model.entity.vehicle.VehicleProfileEntity;
import com.hst.capacity.domain.model.request.vehicle.*;
import com.hst.capacity.domain.model.response.PagingResultVO;
import com.hst.capacity.domain.service.VehicleService;
import com.hst.capacity.infra.convertor.VehicleConvertor;
import com.hst.capacity.infra.persistence.jpa.vehicle.*;
import com.hst.capacity.infra.util.DateUtil;
import com.hst.capacity.infra.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;

/**
 *  "汽车管理"领域服务实现
 *
 * */
@Service
public class VehicleServiceImpl implements VehicleService {

    @Autowired
    VehicleRepository vehicleRepository;
    @Autowired
    VehicleProfileRepository vehicleProfileRepository;
    @Autowired
    DriverCarRepository driverCarRepository;
    @Autowired
    VehicleInsuranceRepository insuranceRepository;
    @Autowired
    VehicleLicenseRepository licenseRepository;

    /**
     * 添加/编辑车辆
     * @param param
     * @return
     */
    @Override
    public VehicleEntity addVehicle(VehicleAddParam param) {
        VehicleProfileEntity profileEntity;
        VehicleEntity vehicleEntity;
        vehicleEntity = vehicleRepository.findByPlateNumber(param.getPlateNumber().toUpperCase().replace(" ",""));
        if (StrUtil.isNotEmpty(param.getIdVehicle())){//编辑
            String plateNumber = vehicleEntity.getPlateNumber();
            try {
                vehicleEntity=vehicleRepository.findById(param.getIdVehicle()).get();
            }catch (NoSuchElementException e){
                throw new BusinessException(5002,"车辆ID[idVehicle]不存在,请检查");
            }
            if (!StrUtil.equals(plateNumber,vehicleEntity.getPlateNumber()))throw new BusinessException(4003,"车辆牌照已经存在,请核对后重新添加");
            //抽取数据更新
            profileEntity=vehicleProfileRepository.findByIdVehicle(vehicleEntity.getIdVehicle());
            if (profileEntity==null)
                throw new BusinessException(5002,"车辆表关系对应有误,请检查");
            VehicleConvertor.INSTANCE.convert(vehicleEntity,param);
            VehicleConvertor.INSTANCE.convert(profileEntity,param);
        }else {//新增
            if (vehicleEntity != null)
                throw new BusinessException(5002,"车辆牌照已经存在,请核对后重新添加");
            vehicleEntity = newVehicle(param);
            profileEntity = newVehicleProfile(param);
            profileEntity.setIdVehicleProfile(StringUtil.generateUuid());
            vehicleEntity.setIdVehicle(StringUtil.generateUuid());
            profileEntity.setIdVehicle(vehicleEntity.getIdVehicle());
        }
        vehicleProfileRepository.save(profileEntity);
        return vehicleRepository.save(vehicleEntity);
    }

    /**
     * 绑定车辆关系(暂废弃)
     * @param param
     * @return
     */
    @Override
    public DriverCarEntity addDriverCar(VehicleRelationParam param) {
        DriverCarEntity driverCarEntity = new DriverCarEntity();
        driverCarEntity.setIdDriverCar(StringUtil.generateUuid());
        driverCarEntity.setIdDriver(param.getIdDriver());
        driverCarEntity.setIdVehicle(param.getIdVehicle());
        driverCarEntity.setPlateNumber(param.getPlateNumber());
        driverCarEntity.setActive(0);
//        driverCarEntity.setCreateBy();
//        driverCarEntity.setCreateTime();
//        driverCarEntity.setUpdateBy();
//        driverCarEntity.setUpdateTime();
        DriverCarEntity save = driverCarRepository.saveAndFlush(driverCarEntity);
        return save;
    }

    /**
     * 条件检索查询车辆
     * @param param
     * @return
     */
    @Override
    public PagingResultVO search(VehicleSearchParam param) {
        List<VehicleEntity> page = vehicleRepository.findAll(new Specification<VehicleEntity>() {
            @Override
            public Predicate toPredicate(Root<VehicleEntity> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                // 定义条件LIST
                List<Predicate> predicates = new ArrayList<Predicate>();
                //idFranchisee
                if (ObjectUtil.isNotEmpty(param.getIdFranchisee())) {
                    predicates.add(criteriaBuilder.equal(root.get("idFranchisee"),param.getIdFranchisee()));
                }
                // regionCode
                if (StrUtil.isNotEmpty(param.getRegionCodes())) {
                    List<String> strings = Convert.toList(String.class, param.getRegionCodes());
                    CriteriaBuilder.In<String> in = criteriaBuilder.in(root.get("regionCode"));
                    for (String v:strings) {
                        in.value(v);
                    }
                    predicates.add(criteriaBuilder.and(in));
                }
                // idAgent
//                if (StrUtil.isNotEmpty(param.getIdAgents())) {
//                    List<String> strings = Convert.toList(String.class, param.getIdAgents());
//                    CriteriaBuilder.In<String> in = criteriaBuilder.in(root.get("idAgent"));
//                    for (String v:strings) {
//                        in.value(v);
//                    }
//                    predicates.add(criteriaBuilder.and(in));
//                }
                // profileEntity.model
                if (StrUtil.isNotEmpty(param.getVehicleModels())) {
                    List<String> strings = Convert.toList(String.class, param.getVehicleModels());
                    CriteriaBuilder.In<String> in = criteriaBuilder.in(root.get("profileEntity").get("model"));
                    for (String v:strings) {
                        in.value(v);
                    }
                    predicates.add(criteriaBuilder.and(in));
                }
                //plateNumber
                if (ObjectUtil.isNotEmpty(param.getPlateNumber())) {
                    predicates.add(criteriaBuilder.equal(root.get("plateNumber"),param.getPlateNumber()));
                }
//                //是否绑定车辆
//                if (ObjectUtil.isNotEmpty(param.getIsBandCar())) {
//                    if (param.getIsBandCar()==1)predicates.add(root.get("driverEntity").get("vehicleEntity").isNotNull());
//                    else predicates.add(root.get("driverEntity").isNotNull());
//                }
                if (ObjectUtil.isEmpty(param.getIsBandCar())||param.getIsBandCar()==1){//没有绑定司机作为条件时不检索司机条件
                    //driverEntity.driverProfile.realName
                    if (ObjectUtil.isNotEmpty(param.getNameDriver())) {
                        predicates.add(criteriaBuilder.like(root.get("driverEntity").get("driverProfile").get("realName"),param.getNameDriver()));
                    }
                    //driverEntity.driverMobile
                    if (ObjectUtil.isNotEmpty(param.getDriverMobile())) {
                        predicates.add(criteriaBuilder.like(root.get("driverEntity").get("driverMobile"),param.getDriverMobile()));
                    }
                }


                //排序
                query.orderBy(criteriaBuilder.desc(root.get("createTime")));
                Predicate[] array = predicates.toArray(new Predicate[0]);
                return criteriaBuilder.and(array);
            }
        });
        //车辆是否被绑定
        List<VehicleEntity> filter = CollUtil.filter(page, new Filter<VehicleEntity>() {
            @Override
            public boolean accept(VehicleEntity vehicleEntity) {
                if (param.getIsBandCar()==null)return true;
//                if (param.getIsBandCar()==0&&vehicleEntity.getDriverEntity()==null) return true;todo 去除oto
//                if (param.getIsBandCar()==1&&vehicleEntity.getDriverEntity()!=null) return true;
                return false;
            }
        });

        return new PagingResultVO((long) filter.size(),filter);
    }

    /**
     * 添加车辆保险
     * @param param
     * @return
     */
    @Override
    public VehicleInsuranceEntity addInsurance(VehicleAddInsuranceParam param) {
        return insuranceRepository.save(newVehicleInsuranceEntity(param));
    }

    /**
     * 添加车辆资质
     * @param param
     * @return
     */
    @Override
    public VehicleLicenseEntity addCertificate(VehicleAddCertificateParam param) {
       return licenseRepository.save(newVehicleLicenseEntity(param));
    }

    /**
     * 编辑查询车辆基本信息
     * @param idVehicle
     * @return
     */
    @Override
    public VehicleAddParam vehicleEditSelectBase(String idVehicle) {
        VehicleEntity vehicle = vehicleRepository.findByIdVehicle(idVehicle);
        if (vehicle==null)throw new BusinessException(5002,"车辆不存在请检查");
        VehicleProfileEntity VehicleP = vehicleProfileRepository.findByIdVehicle(vehicle.getIdVehicle());
        return VehicleConvertor.INSTANCE.convert(vehicle,VehicleP);
    }

    @Override
    public List driverAssociateVehicle(String idFranchisee, String str) {
//        return DriverConvertor.INSTANCE.convert(vehicleRepository.findByIdFranchiseeAndPlateNumberLike(idFranchisee,str));
        return vehicleRepository.findByIdFranchiseeAndPlateNumberLike(idFranchisee,str);
    }

    @Override
    public Boolean vehicleDelete(String id) {
        VehicleEntity vehicleEntity;
        String idVehicle;
        try {
            vehicleEntity = vehicleRepository.findById(id).get();
        }catch (NoSuchElementException E){
            throw new BusinessException(5002,"车辆不存在");
        }
        idVehicle=vehicleEntity.getIdVehicle();
        vehicleRepository.delete(vehicleEntity);
        vehicleProfileRepository.delete(vehicleProfileRepository.findByIdVehicle(idVehicle));
        List<VehicleInsuranceEntity> is = insuranceRepository.findByIdVehicle(idVehicle);
        for (VehicleInsuranceEntity i:is){
            insuranceRepository.delete(i);
        }
        licenseRepository.delete(licenseRepository.findByIdVehicle(idVehicle));
        return true;
    }

    public List<VehicleEntity> searchWithConditions(VehicleRelationParam param) {
        List<VehicleEntity> page = vehicleRepository.findAll(new Specification<VehicleEntity>() {
            @Override
            public Predicate toPredicate(Root<VehicleEntity> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                // 定义条件LIST
                List<Predicate> predicates = new ArrayList<Predicate>();



                //排序
                query.orderBy(criteriaBuilder.desc(root.get("createTime")));
                Predicate[] array = predicates.toArray(new Predicate[0]);
                return criteriaBuilder.and(array);
            }
        });
        return page;
    }

    private VehicleLicenseEntity newVehicleLicenseEntity(VehicleAddCertificateParam param){
        VehicleLicenseEntity vehicleLicenseEntity = new VehicleLicenseEntity();
        VehicleLicenseEntity find;
        if ((find=licenseRepository.findByIdVehicle(param.getIdVehicle()))!=null){
            vehicleLicenseEntity.setIdVehicleLicense(find.getIdVehicleLicense());
        }
        vehicleLicenseEntity.setIdVehicle(param.getIdVehicle());
        vehicleLicenseEntity.setAuthorizer(param.getAuthorizer());
        vehicleLicenseEntity.setServiceRegion(param.getServiceRegion());
        vehicleLicenseEntity.setLicenseNo(param.getLicenseNo());
        vehicleLicenseEntity.setAvtiveDate(DateUtil.parseLocalDateTime(param.getAvtiveDate()));
        vehicleLicenseEntity.setEffectiveDate(DateUtil.parseLocalDateTime(param.getEffectiveDate()));
        vehicleLicenseEntity.setExpiryDate(DateUtil.parseLocalDateTime(param.getExpiryDate()));
        vehicleLicenseEntity.setCertifyDate(DateUtil.parseLocalDateTime(param.getAvtiveDate()));
        vehicleLicenseEntity.setServiceType(param.getServiceType());
        vehicleLicenseEntity.setPossessor(param.getPossessor());
        vehicleLicenseEntity.setPossessorAddress(param.getPossessorAddress());
        vehicleLicenseEntity.setLicenseType(param.getLicenseType());
        vehicleLicenseEntity.setLicensePhoto(param.getLicensePhoto());
//        vehicleLicenseEntity.setCreateBy();
//        vehicleLicenseEntity.setCreateTime();
//        vehicleLicenseEntity.setUpdateBy();
//        vehicleLicenseEntity.setUpdateTime();
        return vehicleLicenseEntity;
    }
    private VehicleInsuranceEntity newVehicleInsuranceEntity(VehicleAddInsuranceParam param){
        VehicleInsuranceEntity vehicleInsuranceEntity = new VehicleInsuranceEntity();
        VehicleInsuranceEntity find;
        if ((find=insuranceRepository.findByIdVehicleAndInsuranceModule(param.getIdVehicle(), param.getInsuranceModule()))!=null){
            vehicleInsuranceEntity.setIdVehicleInsurance(find.getIdVehicleInsurance());
        }
        vehicleInsuranceEntity.setIdVehicle(param.getIdVehicle());
        vehicleInsuranceEntity.setInsuranceCompany(param.getInsuranceCompany());
        vehicleInsuranceEntity.setInsuranceNo(param.getInsuranceNo());
        vehicleInsuranceEntity.setInsuranceType(param.getInsuranceType());
        vehicleInsuranceEntity.setInsuranceModule(param.getInsuranceModule());
        vehicleInsuranceEntity.setInsuranceAmount(param.getInsuranceAmount());
        vehicleInsuranceEntity.setCompensationAmount(param.getCompensationAmount());
        vehicleInsuranceEntity.setEffectiveDate(DateUtil.parseLocalDateTime(param.getEffectiveDate()) );
        vehicleInsuranceEntity.setExpiryDate(DateUtil.parseLocalDateTime(param.getExpiryDate()));
//        vehicleInsuranceEntity.setCreateBy();
//        vehicleInsuranceEntity.setCreateTime();
//        vehicleInsuranceEntity.setUpdateBy();
//        vehicleInsuranceEntity.setUpdateTime();
        return vehicleInsuranceEntity;

    }
    private VehicleEntity newVehicle(VehicleAddParam param){

        VehicleEntity vehicleEntity = new VehicleEntity();
        vehicleEntity.setIdFranchisee(param.getIdFranchisee());
        vehicleEntity.setIdVehicleType(param.getIdVehicleType());
        vehicleEntity.setVehicleName(StrUtil.join(".",param.getBrand(), param.getCarSeries(), param.getModel()));
        vehicleEntity.setPlateNumber(param.getPlateNumber());
        vehicleEntity.setRegionCode(param.getRegionCode());
        vehicleEntity.setTripDistance(param.getTripDistance());
//        vehicleEntity.setLimitDay(param.getLimitDay());
        vehicleEntity.setLimitDay(0);
        vehicleEntity.setBuyDate(DateUtil.parseLocalDateTime(param.getBuyDate()));
        vehicleEntity.setEmployee(param.getEmployee());//指派员工
        vehicleEntity.setCommercialType(param.getCommercialType());
        vehicleEntity.setState(Constants.DEFAULTSTATUS);
        vehicleEntity.setTranFlag(Constants.DEFAULTSTATUS);

        return vehicleEntity;
    }

    private VehicleProfileEntity newVehicleProfile(VehicleAddParam param){
        VehicleProfileEntity vehicleProfileEntity = new VehicleProfileEntity();
//        vehicleProfileEntity.setIdVehicleProfile(StringUtil.generateUuid());
//        vehicleProfileEntity.setIdVehicle();外键
        vehicleProfileEntity.setPlateColor(param.getPlateColor());
        vehicleProfileEntity.setBrand(param.getBrand());
//        vehicleProfileEntity.setType(StrUtil.toString(param.getType()));//车辆详细表与车辆表类型不一致
        vehicleProfileEntity.setModel(param.getModel());
        vehicleProfileEntity.setOwner("");
        vehicleProfileEntity.setColor(param.getColor());
        vehicleProfileEntity.setEngine(param.getEngine());
        vehicleProfileEntity.setVin(param.getVin());
        vehicleProfileEntity.setFuel(param.getFuel());
        vehicleProfileEntity.setPassengerCapacity(param.getPassengerCapacity());
        vehicleProfileEntity.setRegisterDate(DateUtil.parseLocalDateTime(param.getRegisterDate()));
        vehicleProfileEntity.setDisplacement("");
        vehicleProfileEntity.setEnginePower("");
        vehicleProfileEntity.setWheelbase("");
        vehicleProfileEntity.setProvince("");
        vehicleProfileEntity.setCity("");
        vehicleProfileEntity.setDistrict("");
        vehicleProfileEntity.setAddress("");
        vehicleProfileEntity.setIssueDate(DateUtil.parseLocalDateTime(param.getIssueDate()));
        vehicleProfileEntity.setVehicleLicense(param.getVehicleLicense());
        vehicleProfileEntity.setVehicleLicenseSub(param.getVehicleLicenseSub());
        vehicleProfileEntity.setVehiclePhoto(param.getVehiclePhoto());
//        vehicleProfileEntity.setCreateBy();
//        vehicleProfileEntity.setCreateTime();
//        vehicleProfileEntity.setUpdateBy();
//        vehicleProfileEntity.setUpdateTime();
        return vehicleProfileEntity;
    }

    @Override
    public boolean verifyVehicleType(Integer driverVehicleType, Integer orderVehicleType) {
        String vehicleTypeArr = Constants.VehicleTypeMap.get(driverVehicleType);
        boolean result = false;
        if (driverVehicleType == null || orderVehicleType == null) {
            result = false;
        } else if (driverVehicleType == orderVehicleType) {
            result = true;
        } else if (vehicleTypeArr.contains(String.valueOf(orderVehicleType))){
            result = true;
        }
        return result;
    }

}
